package com.example.sixth.coree.controller;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.example.sixth.coree.entity.*;
import com.example.sixth.coree.service.LrcinfoService;
import com.example.sixth.coree.service.SongService;
import com.example.sixth.coree.service.SubscribeinfoService;
import com.example.sixth.coree.service.UserinfoService;
import com.example.sixth.coree.task.SongTask;
import com.example.sixth.coree.utils.MiscUtil;
import com.example.sixth.coree.utils.SpringUtils;
import com.example.sixth.coree.websocketservice.core;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.BoundListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import javax.websocket.Session;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;

@RestController
@CrossOrigin
@RequestMapping("api/song")
public class SongController {
    RedisTemplate redisTemplate= SpringUtils.getBean("redistemp");
    @Autowired
    SongService songService;
    @Autowired
    SubscribeinfoService subscribeinfoService;
    @Autowired
    LrcinfoService lrcinfoService;
    @Autowired
    UserinfoService userinfoService;


    @RequestMapping("addSong")
    ReturnData addSong(@RequestBody Map<String, Object> mp){
        String access_token = mp.get("access_token").toString();
        String user1 = MiscUtil.verifyToken(access_token);
        if(user1==null){
            return new ReturnData(401,"点歌失败",null);
        }
        String room_id = mp.get("room_id").toString();
        Object mid = mp.get("mid");
        /*jdbcTemplate.update("update songinfo set hot=hot+1 where mid=?",mid);*/
        songService.updateSong(Integer.parseInt(mid.toString()));
        Song song = querybyid(mid);
        BoundListOperations roomops = redisTemplate.boundListOps(room_id);
        Long size = roomops.size();
        JSONObject item = new JSONObject();
        String s = user1;
        /*int t1 = jdbcTemplate.queryForList("select * from subscribeinfo where mid=? and user_id=?", Integer.valueOf(mp.get("mid").toString()), Integer.parseInt(s)).size();*/

        if(size==0){
            long l = System.currentTimeMillis();
            item.put("at",false);
            item.put("since",l/1000);
            item.put("song",song);
            item.put("end",(l+Long.valueOf(song.getLength())*1000)/1000);
            item.put("type","playSong");
            item.put("story",null);
            item.put("count",1);
            /*item.put("user",jdbcTemplate.queryForMap("select user_id, user_sex, user_account, user_touchtip, user_name, user_head, user_remark, user_song, user_img from userinfo where user_id=?",s));*/
            item.put("user",userinfoService.queryById(Integer.parseInt(s)));
            SendForALL(room_id,item.toJSONString());

        }else{

            JSONObject jsonObject = JSON.parseObject(roomops.index(size - 1).toString());
            Long since = Long.valueOf(jsonObject.get("end").toString());
            Long length = Long.valueOf(song.getLength().toString());
            item.put("end",since+length);
            item.put("since",since);
            item.put("song",song);
            item.put("type","addSong");
            item.put("story",null);
            item.put("count",1);
            /*item.put("user",jdbcTemplate.queryForMap("select user_id, user_sex, user_account, user_touchtip, user_name, user_head, user_remark, user_song, user_img from userinfo where user_id=?",s));*/
            item.put("user",userinfoService.queryById(Integer.parseInt(s)));
//            JSONObject jtp=new JSONObject();
//            Long second=since%60,min=since/60%60,hour=(since/3600+8)%24;
//            item.put("time",hour+":"+min+":"+second);
//            jtp.put("time",hour+":"+min+":"+second);
//            jtp.put("type","pre");
//            jtp.put("url","https://api.bbbug.com//api/song/playurl?mid="+mid);


            SendForALL(room_id,item.toJSONString());
//            SendForALL(room_id,jtp.toJSONString());
        }


        roomops.rightPush(item.toJSONString());
        /*jdbcTemplate.queryForList("select id from lrcinfo where id=?",mp.get("mid").toString()).size()==0*/
        List<Subscribeinfo> mid1 = subscribeinfoService.querybymid(Integer.parseInt(mp.get("mid").toString()));
        if(mid1.size()==0) {
            redisTemplate.opsForList().rightPush("history", item.toJSONString());
        }
        List<Subscribeinfo> t1 = subscribeinfoService.queryForBoth(Integer.valueOf(mp.get("mid").toString()),Integer.parseInt(s));
        if(t1.size()==0)
            /*jdbcTemplate.update("insert into subscribeinfo (mid,user_id,count) value (?,?,?)", mp.get("mid"), Integer.parseInt(s),1);*/
            subscribeinfoService.insert(Integer.parseInt(mp.get("mid").toString()),Integer.parseInt(s),1);
        else subscribeinfoService.update(Integer.valueOf(mp.get("mid").toString()), Integer.parseInt(s));

        return new ReturnData(200,"歌曲添加成功",mp.get("info"));
    }

    public Song querybyid(Object id){
       /*return jdbcTemplate.queryForMap("select * from songinfo where mid=?",id);*/
        return songService.queryByMid(Integer.parseInt(id.toString()));
    }

    public List<Song>querybyhot(){
        /*List<Map<String, Object>> res = jdbcTemplate.queryForList("select * from songinfo order by hot DESC LIMIT 0,30");*/
        List<Song> res = songService.queryByLimit();
        return res;
    }
    // List<Map<String, Object>>
    public Object querybykey(String key){
        List<Map<String, Object>> res = new Vector<>();
        JSONObject jsonObject=JSON.parseObject(MiscUtil.getres(key));
        JSONObject data = jsonObject.getJSONObject("data");
        BoundHashOperations search_key = redisTemplate.boundHashOps("search_key");
        if(data==null||data.equals(null)){
            return new JSONArray();
            //do nothing
        }else if(search_key.hasKey(key)){
             return search_key.get(key);
        }else{
            JSONArray list = data.getJSONArray("list");
            int len=list.size();

            for(int i=0;i<len;i++){
                HashMap<String, Object> jitem = new HashMap<>();
                JSONObject jtp = list.getJSONObject(i);
                jitem.put("pic",jtp.get("pic"));
                jitem.put("mid",jtp.get("rid"));
                jitem.put("name",jtp.get("name"));
                jitem.put("singer",jtp.get("artist"));
                jitem.put("length",jtp.get("duration"));
                res.add(jitem);
                /*jdbcTemplate.queryForList("select * from songinfo where mid=?",jtp.get("rid")).size()==0*/
                if(songService.queryByMid(Integer.parseInt(jtp.get("rid").toString()))==null){
                    Song song = new Song();
                    song.setMid(Long.parseLong(jtp.get("rid").toString()));
                    song.setName(jtp.get("name").toString());
                    song.setPic(jtp.get("pic").toString());
                    song.setSinger(jtp.get("artist").toString());
                    song.setLength(Integer.parseInt(jtp.get("duration").toString()));
                    song.setHot(0);
                    songService.insert(song);
                }
                /*jdbcTemplate.update("insert into songinfo (mid, name, pic, singer, length,hot) value (?,?,?,?,?,?)",(jtp.get("rid")),jtp.get("name"),jtp.get("pic"),jtp.get("artist"),jtp.get("duration"),0);*/
            }
            search_key.put(key,res);
            return res;

        }
    }
    @RequestMapping("/playurl")
    public void r2(HttpServletResponse response,String mid) throws IOException {
        BoundHashOperations playurl = redisTemplate.boundHashOps("playurl");
        Object mid1 = playurl.get("mid");
        if(mid1==null) {
            URL url = new URL("https://bd.kuwo.cn/url?rid=" + mid + "&type=convert_url3&br=320kmp3");
            BufferedReader r = new BufferedReader(new InputStreamReader(url.openConnection().getInputStream()));
            JSONObject jsonObject;
            try {
                jsonObject = JSON.parseObject(r.readLine());
            }
            catch(Exception e) {
                url = new URL("https://bd.kuwo.cn/url?rid=" + mid + "&type=convert_url3&br=128kmp3");
                r = new BufferedReader(new InputStreamReader(url.openConnection().getInputStream()));
                try {
                    jsonObject = JSON.parseObject(r.readLine());
                }
                catch (Exception x){
                    url = new URL("https://bd.kuwo.cn/url?rid="+mid+"&type=convert_url3&br=128kmp3&from=web&response=url&format=mp3");
                    r = new BufferedReader(new InputStreamReader(url.openConnection().getInputStream()));
                    jsonObject = JSON.parseObject(r.readLine());
                }
            }
            response.sendRedirect(jsonObject.get("url").toString());
        }else{
            response.sendRedirect(mid1.toString());
        }
    }

    @RequestMapping("search")
    public ReturnData search(@RequestBody Map<String, Object> mp){
        if(mp.get("isHots").toString().equals("1")||mp.get("keyword")==null){
            return new ReturnData(200,"success",querybyhot());
        }else{
            return new ReturnData(200,"success",querybykey(mp.get("keyword").toString()));
        }
    }
    @RequestMapping("/getLrc")
    public String getLrc(@RequestBody Map mid){
        /*List<Map<String, Object>> mid1 = jdbcTemplate.queryForList("select * from lrcinfo where id=?", mid.get("mid"));*/
        Lrcinfo lrcinfo = lrcinfoService.queryById(Integer.parseInt(mid.get("mid").toString()));
        if(lrcinfo==null){
            String mid2 = MiscUtil.getLRC(mid.get("mid").toString());
            /*jdbcTemplate.update("insert into lrcinfo (id,lrc) value (?,?)",mid.get("mid"),mid2);*/
            lrcinfoService.insert(Integer.parseInt(mid.get("mid").toString()),mid2);
            return mid2;
        }else{
            String lrc = lrcinfo.getLrc();
            return lrc;
        }


    }
    @RequestMapping("songList")
    ReturnData songList(@RequestBody Map mp){
//        String access_token = mp.get("access_token").toString();
        List<Object> r1 = redisTemplate.opsForList().range(mp.get("room_id").toString(), 1, -1);
        JSONArray jsonArray=new JSONArray();
        for(Object tp1:r1){
            jsonArray.add(JSONObject.parseObject(tp1.toString()));
        }
        return new ReturnData(200,"",jsonArray);
    }
    boolean SendForALL(String room_id,String message){
        ConcurrentHashMap<String, Session> stringSessionConcurrentHashMap = core.CHATMAP.get(room_id);
        for(Session value : stringSessionConcurrentHashMap.values()){
            try {
                value.getBasicRemote().sendText(message);
            } catch (IOException e) {

                e.printStackTrace();
                return false;
            }

        }
        return true;
    }
    @RequestMapping("addMySong")
    ReturnData addMySong(@RequestBody Map mp){
        String userid = MiscUtil.verifyToken(mp.get("access_token").toString());
        if(userid==null){
            return new ReturnData(403,"没权限QWQ",null);
        }else{
            /*int mid = jdbcTemplate.queryForList("select * from subscribeinfo where mid=? and user_id=?", Integer.valueOf(mp.get("mid").toString()), userid).size();*/
            List<Subscribeinfo> subscribeinfo = subscribeinfoService.queryForBoth(Integer.valueOf(mp.get("mid").toString()), Integer.parseInt(userid));
            if(subscribeinfo!=null)subscribeinfoService.update(Integer.valueOf(mp.get("mid").toString()), Integer.parseInt(userid));
             subscribeinfoService.insert(Integer.parseInt(mp.get("mid").toString()), Integer.parseInt(userid),1);
            return new ReturnData(200,"添加至歌单成功",null);
        }
    }
    @RequestMapping("mySongList")
    ReturnData mySongList(@RequestBody Map mp){
        String userid = MiscUtil.verifyToken(mp.get("access_token").toString());
        if(userid==null){
            return new ReturnData(200,"nothing",null);
        }
        else{
            /*List<Map<String, Object>> maps = jdbcTemplate.queryForList("select songinfo.mid, name, pic, singer, length,count as played from songinfo,subscribeinfo where subscribeinfo.user_id=? and subscribeinfo.mid=songinfo.mid", userid);*/
            List<SongSubinfo> maps = songService.queryByUserid(Integer.parseInt(userid));
            return new ReturnData(200,"获取成功",maps);
        }
    }
    @RequestMapping("getusersongs")
    ReturnData getusersongs(@RequestBody Map mp){
        String userid = MiscUtil.verifyToken(mp.get("access_token").toString());
        if(userid==null){
            return new ReturnData(200,"nothing",null);
        }
        else{
            /*List<Map<String, Object>> maps = jdbcTemplate.queryForList("select songinfo.mid, name, pic, singer, length,count as played from songinfo,subscribeinfo where subscribeinfo.user_id=? and subscribeinfo.mid=songinfo.mid", mp.get("user_id"));*/
            List<SongSubinfo> maps = songService.queryByUserid(Integer.parseInt(mp.get("user_id").toString()));
            return new ReturnData(200,"获取成功",maps);
        }
    }
    @RequestMapping("deleteMySong")
    ReturnData deleteMySong(@RequestBody Map mp){
        String userid = MiscUtil.verifyToken(mp.get("access_token").toString());
        if(userid==null){
            return new ReturnData(403,"没权限QWQ",null);
        }else{
            /*int update = jdbcTemplate.update("DELETE FROM  subscribeinfo WHERE mid=? and user_id=? ", mp.get("mid"), userid);*/
            Boolean update = subscribeinfoService.delete(Integer.parseInt(mp.get("mid").toString()),Integer.parseInt(userid));
            if(update){
                return new ReturnData(200,"成功",null);
            }
            return new ReturnData(403,"失败",null);
        }
    }
    @RequestMapping("remove")
    ReturnData removesong(@RequestBody Map mp){
        Long str=System.currentTimeMillis();
        String access_token = mp.get("access_token").toString();
        String s = MiscUtil.verifyToken(access_token);
        Object room_id=mp.get("room_id");
        if(s==null){
            return new ReturnData(403,"无权删除",null);
        }else{
            Long index = Long.parseLong(mp.get("index").toString());

            BoundListOperations boundListOperations = redisTemplate.boundListOps(room_id.toString());
            boundListOperations.remove(1,boundListOperations.index(index+1));
            JSONObject message = new JSONObject();
            message.put("type","removeSong");
            message.put("user_name",mp.get("user_name"));
            message.put("song",querybyid(mp.get("mid")));
            SendForALL(room_id.toString(),message.toJSONString());
            return new ReturnData(200,"删除成功",null);
        }


    }
    @RequestMapping("pass")
    ReturnData passsong(@RequestBody Map mp){
        String access_token = MiscUtil.verifyToken(mp.get("access_token").toString());
        if(access_token==null)return new ReturnData(403,"无权删除!",null);
        String room_id = mp.get("room_id").toString();
        BoundListOperations roomops = redisTemplate.boundListOps(room_id);
        if(roomops.size()<=1){
            return new ReturnData(200,"没有下一首了qwq",null);
        }
        else{
            roomops.leftPop();//删除左侧元素
            SongTask.channelhome.put(room_id,System.currentTimeMillis());
            JSONObject jnow=JSON.parseObject(roomops.index(0).toString());
            jnow.put("since",System.currentTimeMillis()/1000);
            jnow.put("type","playSong");
            SendForALL(room_id,jnow.toJSONString());
            return new ReturnData(200,"成功",null);
        }

    }
        @RequestMapping("push")
          public ReturnData pushsong(@RequestBody Map mp){
            String access_token = MiscUtil.verifyToken(mp.get("access_token").toString());
            if(access_token==null)return new ReturnData(403,"无权顶歌!",null);
            else{
                String room_id = mp.get("room_id").toString();
                BoundListOperations boundListOperations = redisTemplate.boundListOps(room_id);
                Long len=boundListOperations.size();
                Long index = Long.parseLong(mp.get("index").toString());
                if(index<=0||index>len){
                    return new ReturnData(200,"顶你个斐",null);
                }
                JSONObject index1 = JSON.parseObject(boundListOperations.index(index + 1).toString());
                JSONObject index2= JSON.parseObject(boundListOperations.index(index).toString());
                boundListOperations.set(index,index1);
                boundListOperations.set(index+1,index2);
                JSONObject message = new JSONObject();
                message.put("type","push");
                message.put("user_name",mp.get("user_name"));
                message.put("song",querybyid(mp.get("mid")));
                SendForALL(room_id,message.toJSONString());
                return new ReturnData(200,"顶好了",null);
            }
         }

}
